package com.kuang.forkjoin;

import java.util.concurrent.RecursiveTask;

/**
 * ForkJoin    实际好像不太好用，看测试结果，反而时间更长了， Stream流式耗时最小的
 *      分支合并，在JDK1.7
 *      作用：并行情况下，提高效率，大数据量情况下使用！一个线程并发为多个线程使用
 *      特点：工作窃取  B线程执行的快，就会窃取A线程的任务，里面维护的是双端队列（两边都可以操作）
 *
 * 实例：1+2+...10亿求和
 *      1.一般操作 fori,sum+=i;
 *      2.使用ForkJoin（更快）
 *      3.使用Stream并行流（更快）
 *
 * 如何使用ForkJoin?
 *      1.通过 ForkJoinPool()来执行
 *      2.计算任务 forkJoinPool.execute(ForkJoinTask task)
 *              submit()  异步   提交任务，有结果
 *              execute() 同步   执行任务，没有结果
 *      3.计算类继承 extends ForkJoinTask
 *

 *
 */
public class ForkJoinDemo extends RecursiveTask<Long> { //继承JUC递归任务
    private Long start; //1
    private Long end;   //1990900000
    private Long num = 1_0000_0000L; //临界值：小于10w个数相加时，一般方法，大于10w个数相加时，使用ForkJoin/Stream流

    public ForkJoinDemo(Long start, Long end) {
        this.start = start;
        this.end = end;
    }

    // 计算方法
    @Override
    protected Long compute() {
        // 定义一个临界值，如果 <临界值，就用普通求和方式，如果 >临界值，就用ForkJoin
        if ((end - start) < num){
            Long sum = 0L;
            for (Long i = start; i < end; i++) {
                sum += i;
            }
            return sum;
        }else {
            Long middle = (start + end)/2;
            System.out.println("forkjoin middle="+middle);
            ForkJoinDemo task1 = new ForkJoinDemo(start,middle);
            task1.fork();  //拆分任务，把任务压入线程队列
            ForkJoinDemo task2 = new ForkJoinDemo(middle,end);
            task2.fork();  //拆分任务，把任务压入线程队列
            return task1.join()+task2.join(); //分解任务，最终每个分支都走了if里面
        }
    }

}


